﻿using System;
using System.Collections.Generic;
using System.Drawing;

namespace MonoPhysics
{
    /// <summary>
    /// Moteur physique.
    /// </summary>
    public partial class MonoPhysics
    {

        private const float GRAVITY_G = 9.81f;
        public bool TryActivatePotentialBGObject(RigidBody ce)
        {
            if (!this.active)
                return false;

            bool res = false;
            foreach (RigidBody ie in this.interactiveBackgroundElements)
            {
                //throw new NotImplementedException();
                /*if (ie.PosDim.Contains(new PointD((float)ce.Pos.X, (float)ce.Pos.Y)))
                {
                    ((IInteractiveBody)ie).ActivateColludedEffect(ce);
                    res = true;
                }*/
            }
            return res;
        }




        #region Deplacement de objets
        public enum MouvementType { WalkRight = 1, WalkLeft = 2, Jumping = 4, Passive = 0 }
        public enum CollisionZone { Head, Bottom }


        public bool TryMove(MouvementType mType, RigidBody objectToMove, int how)
        {
            if (!this.active)
                return false;
            PhysicContext nPC = objectToMove.PhysicStats;
            Vector walkDir = new Vector();
            if (mType == MouvementType.Passive)
            {
                nPC.PersistantForce = new Force(new Vector(), new Vector()); // vecteur nul.
                nPC.V = new Vector(0, nPC.V.Y, 0);
                objectToMove.PhysicStats = nPC;
                objectToMove.currMouvement = mType;
                return false;
            }
            else
            {
                foreach (Vector v in objectToMove.contactTgts)
                {
                    float dir = v.DirectionDeg;
                    if (dir <= 40 || dir >= 120)// && dir <= 180)//&& v.DirectionDeg > walkDir.DirectionDeg
                    { walkDir = v; }
                }

                if (!walkDir.isNull())
                {
                    walkDir = walkDir.direction().reflexion();
                    //nPC.V = new Vector(0, 0, 0);
                }
                else
                {
                    walkDir = new Vector(0.25f, 0, 0);
                    //Console.WriteLine("THE DIRECTION: " + walkDir.ToString());
                }
                //if (walkDir.X == float.NaN || walkDir.Y == float.NaN)
                //Console.WriteLine("NAN");
                Force walkForce = new Force(walkDir * objectToMove.M * how, new Vector());
                nPC.PersistantForce = walkForce;
                objectToMove.PhysicStats = nPC;
                objectToMove.currMouvement = mType;
                objectToMove.Sleeping = false;
                return true;
            }
        }

        public bool isTryMoveable(RigidBody objectToMove)
        {
            foreach (Vector v in objectToMove.contactTgts)
            {
                float dir = v.DirectionDeg;
                if (!(dir <= 60 || dir >= 120))// && dir <= 180))//&& v.DirectionDeg > walkDir.DirectionDeg
                { return false; }
            }
            return true;
        }

        public bool isTryJumpable(RigidBody rb)
        {
            bool maybe = false;
            float ymax = rb.Shape.BoundingBox.YMax.Value.value;
            float posy = rb.Pos.Y;
            if (rb.CollisionPoints.Count == 0 || rb.contactTgts.Count == 0)
                return false;
            foreach (PointD pt in rb.CollisionPoints)
            {
                if (pt.Y > 0)
                {
                    maybe = true;
                    break;
                }
            }
            if (!maybe)
                return false;
            maybe = false;
            foreach (Vector v in rb.contactTgts)
            {
                float dir = v.DirectionDeg;
                if ((dir <= 40 || dir >= 140 && dir <= 180))//&& v.DirectionDeg > walkDir.DirectionDeg
                { maybe = true; break; }
            }
            return maybe;
        }

        public bool TryJump(MouvementType mt, RigidBody objectToJump)
        {
            if (!active || mt == MouvementType.Passive)
                return false;
            /*bool canJump = false;
            
            foreach (Vector v in objectToJump.contactTgts)
            {
                if (v.DirectionDeg <= 20 || v.DirectionDeg >= 160 && v.DirectionDeg <= 180)//&& v.DirectionDeg > walkDir.DirectionDeg
                { canJump = true; }
            }
            if (!canJump)
                return;
            //*/
            if (!objectToJump.Sleeping && !isTryJumpable(objectToJump))
                return false;
            float xmagn = 0;
            if (objectToJump.currMouvement == MouvementType.WalkLeft)
                xmagn = -15000;
            else if (objectToJump.currMouvement == MouvementType.WalkRight)
                xmagn = 15000;
            objectToJump.PhysicStats.Forces.Clear();
            objectToJump.PhysicStats.ExtraForces.Clear();
            objectToJump.PhysicStats.Forces.Add(new Force(new Vector(xmagn, -GRAVITY_G * objectToJump.M * 10000, 0), new Vector()));
            PhysicContext npc = objectToJump.PhysicStats;
            objectToJump.Sleeping = false;
            //npc.V = new Vector(xmagn, -GRAVITY_G * 20, 0);
            //objectToJump.PhysicStats = npc;
            return true;
        }



        public CollisionZone GetCollisionZone(Collision cc, RigidBody ce)
        {
            float intLimite = ce.ShapePosDim.Height / 6;  // Head: 5/6 // Bottom: 1/6
            if (cc.collisionPoint.Y - ce.ShapePosDim.Y < intLimite * 5)
                return CollisionZone.Head;
            else
                return CollisionZone.Bottom;
        }
        #endregion
    }
}
